<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    />
    <meta
      name="description"
      content="Moon terrain visualized using 3D Tiles, tiled and hosted by Cesium ion, and shown with points of interest and additional data layers."
    />
    <meta name="cesium-sandcastle-labels" content="Showcases, ion Assets, 3D Tiles" />
    <title>Cesium Moon Terrain</title>
    <script type="text/javascript" src="../Sandcastle-header.js"></script>
    <script
      type="text/javascript"
      src="../../../Build/CesiumUnminified/Cesium.js"
      nomodule
    ></script>
    <script type="module" src="../load-cesium-es6.js"></script>
  </head>
  <body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
    <style>
      @import url(../templates/bucket.css);
      #toolbar {
        background: rgba(42, 42, 42, 0.8);
        padding: 4px;
        border-radius: 4px;
      }
      #toolbar input {
        vertical-align: middle;
        padding-top: 2px;
        padding-bottom: 2px;
      }
      #toolbar .header {
        font-weight: bold;
      }
    </style>
    <div id="cesiumContainer" class="fullSize"></div>
    <div id="loadingOverlay"><h1>Loading...</h1></div>
    <div id="toolbar"></div>
    <script id="cesium_sandcastle_script">
      window.startup = async function (Cesium) {
        "use strict";
        //Sandcastle_Begin
        // Set the ellipsoid to be the moon before creating the viewer
        Cesium.Ellipsoid.default = Cesium.Ellipsoid.MOON;

        const viewer = new Cesium.Viewer("cesiumContainer", {
          terrainProvider: false,
          baseLayer: false,
          timeline: false,
          animation: false,
          baseLayerPicker: false,
          geocoder: false,
          shadows: true,
        });

        const scene = viewer.scene;

        // Add Moon Terrain 3D Tiles
        try {
          const tileset1 = await Cesium.Cesium3DTileset.fromIonAssetId(2684829, {
            // Allow clamp to 3D Tiles
            enableCollision: true,
          });
          viewer.scene.primitives.add(tileset1);
        } catch (error) {
          console.log(`Error loading tileset: ${error}`);
        }

        // Boundary data from https://wms.lroc.asu.edu/lroc/view_rdr/SHAPEFILE_LROC_GLOBAL_MARE
        const boundariesResource = await Cesium.IonResource.fromAssetId(2683530);
        const boundarySource = await Cesium.GeoJsonDataSource.load(boundariesResource, {
          clampToGround: true,
          fill: Cesium.Color.fromBytes(26, 106, 113).withAlpha(0.6),
        });
        boundarySource.show = false;
        viewer.dataSources.add(boundarySource);

        // Possible Artemis 3 landing locations. data from https://files.actgate.com/lunar/A3_Named_regions.geojson
        const artemis3resource = await Cesium.IonResource.fromAssetId(2683531);
        const artemis3Source = await Cesium.GeoJsonDataSource.load(artemis3resource, {
          clampToGround: true,
          fill: Cesium.Color.fromBytes(243, 242, 99).withAlpha(0.6),
        });
        artemis3Source.show = false;
        viewer.dataSources.add(artemis3Source);

        // Positions courtesy of https://www.sciencedirect.com/science/article/abs/pii/S0019103516301518?via%3Dihub
        const pointsOfInterest = [
          {
            text: "Apollo 11",
            latitude: 0.67416,
            longitude: 23.47315,
          },
          {
            text: "Apollo 14",
            latitude: -3.64417,
            longitude: 342.52135,
          },
          {
            text: "Apollo 15",
            latitude: 26.13341,
            longitude: 3.6285,
          },
          {
            text: "Lunokhod 1",
            latitude: 38.2378,
            longitude: -35.0017,
          },
          {
            text: "Lunokhod 2",
            latitude: 25.83232,
            longitude: 30.92215,
          },
        ];

        for (const poi of pointsOfInterest) {
          viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(poi.longitude, poi.latitude),
            label: {
              text: poi.text,
              font: "14pt Verdana",
              outlineColor: Cesium.Color.DARKSLATEGREY,
              outlineWidth: 2,
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              pixelOffset: new Cesium.Cartesian2(0, -22),
              scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.5),
              translucencyByDistance: new Cesium.NearFarScalar(2.5e7, 1.0, 4.0e7, 0.0),
              heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
              disableDepthTestDistance: new Cesium.CallbackProperty(() => {
                return Cesium.Cartesian3.magnitude(scene.camera.positionWC);
              }, false),
            },
            point: {
              pixelSize: 10,
              color: Cesium.Color.fromBytes(243, 242, 99),
              outlineColor: Cesium.Color.fromBytes(219, 218, 111),
              outlineWidth: 2,
              scaleByDistance: new Cesium.NearFarScalar(1.5e3, 1.0, 4.0e7, 0.1),
              heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
              disableDepthTestDistance: new Cesium.CallbackProperty(() => {
                return Cesium.Cartesian3.magnitude(scene.camera.positionWC);
              }, false),
            },
          });
        }

        const seaOfTranquility = {
          destination: new Cesium.Cartesian3(
            2134594.9298812235,
            1256488.0678322134,
            379606.9284823841,
          ),
          orientation: {
            direction: new Cesium.Cartesian3(
              -0.8518395698371783,
              -0.5014189063342804,
              -0.1514873843927112,
            ),
            up: new Cesium.Cartesian3(
              -0.13054959630640847,
              -0.07684549781463353,
              0.9884591910493093,
            ),
          },
          easingFunction: Cesium.EasingFunction.LINEAR_NONE,
        };

        const apollo11 = {
          destination: new Cesium.Cartesian3(
            1609100.311044896,
            733266.0643925276,
            53608.976740262646,
          ),
          orientation: {
            direction: new Cesium.Cartesian3(
              -0.41704286323660256,
              -0.7222280712427744,
              -0.5517806297183315,
            ),
            up: new Cesium.Cartesian3(
              0.8621189850799429,
              -0.12210806245903304,
              -0.49177278965720556,
            ),
          },
          easingFunction: Cesium.EasingFunction.LINEAR_NONE,
        };

        const copernicus = {
          destination: new Cesium.Cartesian3(
            1613572.8201475781,
            -677039.3827805589,
            339559.7958496013,
          ),
          orientation: {
            direction: new Cesium.Cartesian3(
              -0.10007925201262617,
              0.8771366500325052,
              -0.4696971795597116,
            ),
            up: new Cesium.Cartesian3(
              0.9948921707513932,
              0.08196514973381885,
              -0.058917593354560566,
            ),
          },
          easingFunction: Cesium.EasingFunction.LINEAR_NONE,
        };

        const tycho = {
          destination: new Cesium.Cartesian3(
            1368413.3560818078,
            -166198.00035620513,
            -1203576.7397013502,
          ),
          orientation: {
            direction: new Cesium.Cartesian3(
              -0.8601315724135887,
              -0.5073902275496569,
              0.05223825345888711,
            ),
            up: new Cesium.Cartesian3(
              0.2639103814694499,
              -0.5303301783281616,
              -0.8056681776681204,
            ),
          },
          easingFunction: Cesium.EasingFunction.LINEAR_NONE,
        };

        const shackleton = {
          destination: Cesium.Rectangle.fromBoundingSphere(
            new Cesium.BoundingSphere(
              new Cesium.Cartesian3(
                -17505.087036391753,
                38147.40236305639,
                -1769721.5748224584,
              ),
              40000.0,
            ),
          ),
          orientation: {
            direction: new Cesium.Cartesian3(
              0.2568703591904826,
              -0.6405212914728244,
              0.7237058060699372,
            ),
            up: new Cesium.Cartesian3(
              0.26770932874967773,
              -0.6723714327527822,
              -0.6901075073627064,
            ),
          },
          easingFunction: Cesium.EasingFunction.LINEAR_NONE,
        };

        const camera = viewer.scene.camera;
        const rotationSpeed = Cesium.Math.toRadians(0.1);
        const removeRotation = viewer.scene.postRender.addEventListener(
          function (scene, time) {
            viewer.scene.camera.rotateRight(rotationSpeed);
          },
        );

        const options1 = [
          {
            text: "Fly to...",
            onselect: () => {},
          },
          {
            text: "Sea of Tranquility",
            onselect: function () {
              removeRotation();
              scene.camera.flyTo(seaOfTranquility);
              artemis3Source.show = false;
            },
          },
          {
            text: "Apollo 11 Landing Site",
            onselect: () => {
              removeRotation();
              scene.camera.flyTo(apollo11);
              artemis3Source.show = false;
            },
          },
          {
            text: "Copernicus Crater",
            onselect: () => {
              removeRotation();
              scene.camera.flyTo(copernicus);
              artemis3Source.show = false;
            },
          },
          {
            text: "Tycho Crater",
            onselect: () => {
              removeRotation();
              scene.camera.flyTo(tycho);
              artemis3Source.show = false;
            },
          },
          {
            text: "Shackleton Crater (South Pole) and Artemis 3 landing options",
            onselect: () => {
              removeRotation();
              scene.camera.flyTo(shackleton);
              artemis3Source.show = true;
            },
          },
        ];
        Sandcastle.addToolbarMenu(options1);

        Sandcastle.addToggleButton("Show Mare Boundaries", false, function (checked) {
          boundarySource.show = checked;
        });

        // Spin the moon on first load but disable the spinning upon any input
        const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
        handler.setInputAction(
          () => removeRotation(),
          Cesium.ScreenSpaceEventType.LEFT_DOWN,
        );
        handler.setInputAction(
          () => removeRotation(),
          Cesium.ScreenSpaceEventType.RIGHT_DOWN,
        );
        handler.setInputAction(
          () => removeRotation(),
          Cesium.ScreenSpaceEventType.MIDDLE_DOWN,
        );
        handler.setInputAction(() => removeRotation(), Cesium.ScreenSpaceEventType.WHEEL);

        //Sandcastle_End
      };
      if (typeof Cesium !== "undefined") {
        window.startupCalled = true;
        window.startup(Cesium).catch((error) => {
          "use strict";
          console.error(error);
        });
        Sandcastle.finishedLoading();
      }
    </script>
  </body>
</html>
